package es.tikitaka.actions.jugadores;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.FlushModeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.FacesMessages;
import org.richfaces.event.UploadEvent;
import org.richfaces.model.UploadItem;

import es.tikitaka.dao.DireccionService;
import es.tikitaka.dao.JugadorService;
import es.tikitaka.dao.MunicipioDicService;
import es.tikitaka.dao.PartEquipoService;
import es.tikitaka.dao.PartJugadorService;
import es.tikitaka.dao.PieDicService;
import es.tikitaka.dao.PosicionDicService;
import es.tikitaka.dao.ProvinciaDicService;
import es.tikitaka.dictionary.MunicipioDic;
import es.tikitaka.dictionary.PieDic;
import es.tikitaka.dictionary.PosicionDic;
import es.tikitaka.dictionary.ProvinciaDic;
import es.tikitaka.domain.Direccion;
import es.tikitaka.domain.Temporada;
import es.tikitaka.domain.equipo.PartEquipo;
import es.tikitaka.domain.jugador.Jugador;
import es.tikitaka.domain.jugador.PartJugador;
import es.tikitaka.domain.liga.Jornada;
import es.tikitaka.domain.liga.PartidoL;

/**
 * 
 * @author Saúl Domínguez
 * @since 2010
 * @category PFC
 */

@Name("jugadorAction")
@Scope(ScopeType.CONVERSATION)
public class JugadorAction {

	private int modo;
	private boolean nuevo;

	private Jugador jugador;
	private String dni;
	private PartJugador participacion;
	private PartJugador nextParticipacion;
	private PartEquipo partEquipo;

	private Jugador newJugador;
	private Integer edad;
	private boolean guardado = false;

	private String fotoJFileName;
	private byte[] fotoJ;

	private byte[] fotografia;

	private List<ProvinciaDic> listaProvincias;
	private List<MunicipioDic> listaMunicipios;
	private List<ProvinciaDic> listaProvinciasDir;
	private List<MunicipioDic> listaMunicipiosDir;
	private List<PartJugador> listaParticipaciones;
	private List<PartEquipo> listaEquiposTemporada;
	private List<PosicionDic> listaPosiciones;
	private List<PieDic> listaPies;

	private PieDic pie;
	private PosicionDic posicion;
	private Integer dorsal;

	@In(create = true)
	private ProvinciaDicService provinciaService;

	@In(create = true)
	private MunicipioDicService municipioService;

	@In(create = true)
	private JugadorService jugadorService;

	@In(create = true)
	private DireccionService direccionService;

	@In(create = true)
	private JugadorSearch jugadorSearch;

	@In(create = true)
	private PartJugadorService partJugadorService;

	@In(create = true)
	private PartEquipoService partEquipoService;

	@In(create = true)
	private PosicionDicService posicionService;

	@In(create = true)
	private PieDicService pieService;

	/**
	 * Constructor por defecto
	 */
	public JugadorAction() {
		// TODO Auto-generated constructor stub
	}

	public void subirFotografia(UploadEvent event) {
		UploadItem item = event.getUploadItem();

		fotografia = item.getData();
	}

	/**
	 * Método para la creación de un nuevo jugador
	 * 
	 */
	public void nuevoJugador() {
		newJugador = new Jugador();
		listaProvincias = provinciaService.getList();
		listaProvinciasDir = provinciaService.getList();
		Direccion dir = new Direccion();
		newJugador.setDireccion(dir);
		nuevo = true;
		guardado = false;
	}

	/**
	 * Método para seleccionar a un jugador de los resultados de una consulta
	 * para realizar sobre él las acciones determinadas por el modo de selección
	 * 
	 * @param player
	 *            Jugador seleccionado de la tabla de resultados
	 * @param md
	 *            Modo de selección, edición, consulta, alta o baja
	 */
	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void selectJugador(Jugador player, int md) {
		jugador = player;
		dni = jugador.getDni();
		modo = md;
		listaProvincias = provinciaService.getList();
		listaProvinciasDir = provinciaService.getList();
		listaParticipaciones = partJugadorService.getParticipaciones(jugador);
		nuevo = false;
		guardado = false;

		if (jugadorSearch.getTemporada() != null) {
			Temporada t = jugadorSearch.getTemporada();
			for (PartJugador p : listaParticipaciones) {
				if (p.getTemporada().equals(t)) {
					participacion = p;
					if (participacion.getEquipo() != null) {
						partEquipo = participacion.getEquipo();
					}
					if (participacion.getPosicion() != null) {
						posicion = participacion.getPosicion();
					}
					dorsal = participacion.getDorsal();
					listaEquiposTemporada = partEquipoService
							.getEquiposTemporada(participacion.getTemporada());
					listaPies = pieService.getList();
					listaPosiciones = posicionService.getList();
				}
			}
		}
	}

	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void selectTemporada() {
		if (nextParticipacion != null) {
			participacion = (PartJugador) nextParticipacion;
			if (participacion.getEquipo() != null) {
				partEquipo = nextParticipacion.getEquipo();
			}
			if (participacion.getPosicion() != null) {
				posicion = nextParticipacion.getPosicion();
			}
			dorsal = nextParticipacion.getDorsal();
			listaEquiposTemporada = partEquipoService
					.getEquiposTemporada(nextParticipacion.getTemporada());
			listaPies = pieService.getList();
			listaPosiciones = posicionService.getList();
		}
	}

	/**
	 * Método para comprobar si la temporada ha comenzado o no para ver si se
	 * puede editar sus datos
	 * 
	 * @param tempo
	 * @return
	 */
	public boolean comprobarInicioTemporada() {
		boolean comenzada = false;
		if (participacion != null) {
			if (participacion.getTemporada().getLiga().getCalendario() != null) {
				List<Jornada> jornadas = new ArrayList<Jornada>();
				jornadas.addAll(participacion.getTemporada().getLiga()
						.getCalendario().getM_jornadas());
				Collections.sort(jornadas);
				Iterator it = jornadas.get(0).getM_partidos().iterator();
				while (it.hasNext() && !comenzada) {
					PartidoL p = (PartidoL) it.next();
					if (p.getEstado().equals("comenzado") || p.isFin()) {
						comenzada = true;
					}
				}
			}
		}
		return comenzada;
	}

	/**
	 * Método para calcular la edad de un jugador a partir de su fecha de
	 * nacimiento
	 */
	public void calculaEdad() {
		if (nuevo) {
			if (newJugador.getFechaNac() != null) {
				Long fecNac = newJugador.getFechaNac().getTime();
				Date d = new Date();
				Long hoy = d.getTime();

				Long dif = hoy - fecNac;

				long mili = 365 * 24 * 60 * 60;
				dif = dif / mili;
				dif = dif / 1000;

				edad = Long.valueOf(dif).intValue();

			} else {
				edad = 0;
			}
		} else {
			if (jugador.getFechaNac() != null) {
				Long fecNac = jugador.getFechaNac().getTime();
				Date d = new Date();
				Long hoy = d.getTime();

				Long dif = hoy - fecNac;

				long mili = 365 * 24 * 60 * 60;
				dif = dif / mili;
				dif = dif / 1000;

				edad = Long.valueOf(dif).intValue();

			} else {
				edad = 0;
			}
		}
	}

	/**
	 * Método para obtener una fotografía subida por un usuario
	 */
	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void obtenerFotografia(UploadEvent event) throws Exception {

		UploadItem item = event.getUploadItem();

		fotoJ = item.getData();
		fotoJFileName = item.getFileName();
		if (fotoJ != null) {
			FacesMessages.instance().add("Fotografia subida correctamente");
			if (nuevo) {
				newJugador.setFoto(fotoJ);
			} else {
				jugador.setFoto(fotoJ);
				FacesMessages.instance().add("Fotografía subida correctamente");
			}
		} else {
			FacesMessages.instance().add("No se ha subida ninguna fotografía");
		}

	}

	public void deletePhoto() {
		if (nuevo) {
			if (newJugador.getFoto() != null) {
				newJugador.setFoto(null);
				FacesMessages.instance().add(
						"Fotografía eliminada correctamente");
			}
		} else {
			if (jugador.getFoto() != null) {
				jugador.setFoto(null);
				FacesMessages.instance().add(
						"Fotografía eliminada correctamente");
			}
		}
	}

	/**
	 * Método para guardar las modificaciones realizadas a un jugador
	 * 
	 */
	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void guardar() {

		guardado = false;

		if (comprobarNombre()) {
			if (comprobarDni()) {
				if (comprobarFechaNac()) {
					if (comprobarMunicipio()) {
						if (nuevo) {

							Direccion d = direccionService.buscar(newJugador
									.getDireccion().getDireccion(), newJugador
									.getDireccion().getProvincia(), newJugador
									.getDireccion().getMunicipio());

							if (d == null) {
								boolean gdir = direccionService.save(newJugador
										.getDireccion());

								if (gdir) {
									guardado = jugadorService.save(newJugador);
								} else {
									guardado = false;
									FacesMessages.instance().add(
											"Error al guardar la dirección");
								}
							} else {
								newJugador.setDireccion(d);
								guardado = jugadorService.save(newJugador);
							}
						} else {
							boolean gdir = direccionService.save(jugador
									.getDireccion());
							if (gdir) {
								jugador.setDni(dni);
								guardado = jugadorService.save(jugador);
							} else {
								guardado = false;
								FacesMessages.instance().add(
										"Error al guardar la direccion");
							}
						}
						if (guardado) {
							if (nuevo) {
								FacesMessages
										.instance()
										.add(
												"Se ha registrado el nuevo jugador con éxito.");
							} else {
								FacesMessages
										.instance()
										.add(
												"Se han modificado los datos del jugador con éxito.");
							}
						} else {
							FacesMessages
									.instance()
									.add(
											"Se ha producido un error y no se ha podido completar el proceso de registro.");
						}
					}
				}
			}
		}
	}

	/**
	 * Método que comprueba el nombre del jugador ya sea de nuevo registro o un
	 * jugador ya existente
	 * 
	 * @return estado de la comprobación
	 */
	public boolean comprobarNombre() {

		boolean estado = false;

		if (nuevo) {
			if (newJugador.getNombre() != null
					&& newJugador.getNombre().length() > 0) {
				estado = true;
			}
		} else {
			if (jugador.getNombre() != null && jugador.getNombre().length() > 0) {
				estado = true;
			}
		}

		if (!estado) {
			FacesMessages.instance().add(
					"Debes introducir un nombre para el jugador.");
		}

		return estado;
	}

	/**
	 * Método que comrpueba el dni del jugador ya sea de nuevo registro o un
	 * jugador ya existente
	 * 
	 * @return estado de la comprobación
	 */
	public boolean comprobarDni() {

		boolean estado = false;

		if (nuevo) {
			if (newJugador.getDni() != null
					&& newJugador.getDni().length() == 9) {
				estado = jugadorService.existeDni(newJugador.getDni());
			} else {
				FacesMessages
						.instance()
						.add(
								"El Dni del jugador debe estar relleno y tener 9 caracteres.");
				return false;
			}
		} else {
			if (dni != null && dni.length() == 9) {
				if (!dni.equals(jugador.getDni())) {
					estado = jugadorService.existeDni(dni);
				} else {
					estado = true;
				}
			} else {
				FacesMessages
						.instance()
						.add(
								"El Dni del jugador debe estar relleno y tener 9 caracteres.");
				return false;
			}
		}

		if (!estado) {
			FacesMessages
					.instance()
					.add(
							"El Dni que introduce pertenece a otra persona ya registrada en la aplicación.");
		}

		return estado;
	}

	/**
	 * Método que comprueba la fecha de naciemiento del jugador ya sea de nuevo
	 * registro o un jugador ya existente
	 * 
	 * @return estado de la comprobación
	 */
	public boolean comprobarFechaNac() {

		boolean estado = false;

		if (nuevo) {
			if (newJugador.getFechaNac() != null && edad >= 16) {
				estado = true;
			}
		} else {
			if (jugador.getFechaNac() != null && edad >= 16) {
				estado = true;
			}
		}

		if (!estado) {
			FacesMessages
					.instance()
					.add(
							"Debes introducir una fecha de nacimiento válida (edad superior o igual a 16 años).");
		}

		return estado;
	}

	/**
	 * Método que comprueba el municipio del jugador ya sea de nuevo registro o
	 * un jugador ya existente
	 * 
	 * @return estado de la comprobación
	 */
	public boolean comprobarMunicipio() {

		boolean estado = false;

		if (nuevo) {
			if (newJugador.getMunicipio() != null) {
				estado = true;
			}
		} else {
			if (jugador.getMunicipio() != null) {
				estado = true;
			}
		}

		if (!estado) {
			FacesMessages.instance().add(
					"Debes introducir un municipio para el jugador");
		}

		return estado;
	}

	/**
	 * Método para cargar un equipo en la participación seleccionada
	 */
	public void cargaParticipacion() {
		if (partEquipo != null) {
			participacion.setEquipo(partEquipo);
		}
	}

	/**
	 * Método para limpiar los datos introducidos en el formulario de
	 * jugador/nuevo jugador
	 */
	public void limpiar() {
		newJugador = null;
		jugador = null;
		edad = null;
		fotoJ = null;
		fotoJFileName = null;
		listaMunicipios = null;
		listaMunicipiosDir = null;
	}

	/**
	 * Método para inicializar todos los parámetros al volver al menú de
	 * búsqueda de jugadores
	 */
	public void volver() {
		jugadorService.merge(jugador);
		limpiar();
	}

	/**
	 * Método para inicializar todos los parámetros al volver al menú principal
	 */
	@End
	public void menu() {
		limpiar();
		jugadorSearch.limpiar();
	}

	/*
	 * getters and setters
	 */

	/**
	 * 
	 * @return
	 */
	public int getModo() {
		return modo;
	}

	/**
	 * 
	 * @param modo
	 */
	public void setModo(int modo) {
		this.modo = modo;
	}

	/**
	 * 
	 * @return
	 */
	public boolean isNuevo() {
		return nuevo;
	}

	/**
	 * 
	 * @param nuevo
	 */
	public void setNuevo(boolean nuevo) {
		this.nuevo = nuevo;
	}

	/**
	 * 
	 * @return
	 */
	public Jugador getJugador() {
		return jugador;
	}

	/**
	 * 
	 * @param jugador
	 */
	public void setJugador(Jugador jugador) {
		this.jugador = jugador;
	}

	/**
	 * 
	 * @return
	 */
	public String getDni() {
		return dni;
	}

	/**
	 * 
	 * @param dni
	 */
	public void setDni(String dni) {
		this.dni = dni;
	}

	/**
	 * 
	 * @return
	 */
	public PartJugador getParticipacion() {
		return participacion;
	}

	/**
	 * 
	 * @param participacion
	 */
	public void setParticipacion(PartJugador participacion) {
		this.participacion = participacion;
	}

	/**
	 * 
	 * @return
	 */
	public PartJugador getNextParticipacion() {
		return nextParticipacion;
	}

	/**
	 * 
	 * @param nextParticipacion
	 */
	public void setNextParticipacion(PartJugador nextParticipacion) {
		this.nextParticipacion = nextParticipacion;
	}

	/**
	 * 
	 * @return
	 */
	public PartEquipo getPartEquipo() {
		return partEquipo;
	}

	/**
	 * 
	 * @param partEquipo
	 */
	public void setPartEquipo(PartEquipo partEquipo) {
		this.partEquipo = partEquipo;
	}

	/**
	 * @return
	 */
	public Jugador getNewJugador() {
		return newJugador;
	}

	/**
	 * 
	 * @param newJugador
	 *            Jugador nuevo jugador a dar de alta
	 */
	public void setNewJugador(Jugador newJugador) {
		this.newJugador = newJugador;
	}

	/**
	 * 
	 * @return guardado True o false si se guarda correctamente o no
	 */
	public boolean isGuardado() {
		return guardado;
	}

	/**
	 * 
	 * @param guardado
	 */
	public void setGuardado(boolean guardado) {
		this.guardado = guardado;
	}

	/**
	 * 
	 * @return
	 */
	public String getFotoJFileName() {
		return fotoJFileName;
	}

	/**
	 * 
	 * @param fotoJFileName
	 */
	public void setFotoJFileName(String fotoJFileName) {
		this.fotoJFileName = fotoJFileName;
	}

	/**
	 * 
	 * @return
	 */
	public byte[] getFotoJ() {
		return fotoJ;
	}

	/**
	 * 
	 * @param fotoJ
	 */
	public void setFotoJ(byte[] fotoJ) {
		this.fotoJ = fotoJ;
	}

	/**
	 * 
	 * @return listaProvincias Lista de provincias
	 */
	public List<ProvinciaDic> getListaProvincias() {
		if (listaProvincias == null) {
			listaProvincias = provinciaService.getList();
		}
		return listaProvincias;
	}

	/**
	 * 
	 * @param listaProvincias
	 *            List<ProvinciaDic>
	 */
	public void setListaProvincias(List<ProvinciaDic> listaProvincias) {
		this.listaProvincias = listaProvincias;
	}

	/**
	 * 
	 * @return listaMunicipios Lista de municipios dependiendo de la provincia
	 *         seleccionada
	 */
	public List<MunicipioDic> getListaMunicipios() {
		if (nuevo) {
			if (newJugador.getProvincia() != null) {
				listaMunicipios = municipioService.getList(newJugador
						.getProvincia());
			}
		} else {
			if (jugador.getProvincia() != null) {
				listaMunicipios = municipioService.getList(jugador
						.getProvincia());
			}
		}
		return listaMunicipios;
	}

	/**
	 * 
	 * @param listaMunicipios
	 *            List<MunicipioDic>
	 */
	public void setListaMunicipios(List<MunicipioDic> listaMunicipios) {
		this.listaMunicipios = listaMunicipios;
	}

	/**
	 * 
	 * @return
	 */
	public List<ProvinciaDic> getListaProvinciasDir() {
		return listaProvinciasDir;
	}

	/**
	 * 
	 * @param listaProvinciasDir
	 */
	public void setListaProvinciasDir(List<ProvinciaDic> listaProvinciasDir) {
		this.listaProvinciasDir = listaProvinciasDir;
	}

	/**
	 * 
	 * @return
	 */
	public List<MunicipioDic> getListaMunicipiosDir() {
		if (nuevo) {
			if (newJugador.getDireccion() != null) {
				if (newJugador.getDireccion().getProvincia() != null) {
					listaMunicipiosDir = municipioService.getList(newJugador
							.getDireccion().getProvincia());
				}
			}
		} else {
			if (jugador.getDireccion() != null) {
				if (jugador.getDireccion().getProvincia() != null) {
					listaMunicipiosDir = municipioService.getList(jugador
							.getDireccion().getProvincia());
				}
			}
		}
		return listaMunicipiosDir;
	}

	/**
	 * 
	 * @param listaMunicipiosDir
	 */
	public void setListaMunicipiosDir(List<MunicipioDic> listaMunicipiosDir) {
		this.listaMunicipiosDir = listaMunicipiosDir;
	}

	/**
	 * 
	 * @return
	 */
	public List<PartJugador> getListaParticipaciones() {
		return listaParticipaciones;
	}

	/**
	 * 
	 * @return
	 */
	public List<PartEquipo> getListaEquiposTemporada() {
		return listaEquiposTemporada;
	}

	/**
	 * 
	 * @param listaEquiposTemporada
	 */
	public void setListaEquiposTemporada(List<PartEquipo> listaEquiposTemporada) {
		this.listaEquiposTemporada = listaEquiposTemporada;
	}

	/**
	 * 
	 * @return
	 */
	public List<PosicionDic> getListaPosiciones() {
		return listaPosiciones;
	}

	/**
	 * 
	 * @param listaPosiciones
	 */
	public void setListaPosiciones(List<PosicionDic> listaPosiciones) {
		this.listaPosiciones = listaPosiciones;
	}

	/**
	 * 
	 * @return
	 */
	public List<PieDic> getListaPies() {
		return listaPies;
	}

	/**
	 * 
	 * @param listaPies
	 */
	public void setListaPies(List<PieDic> listaPies) {
		this.listaPies = listaPies;
	}

	/**
	 * 
	 * @return
	 */
	public PieDic getPie() {
		return pie;
	}

	/**
	 * 
	 * @param pie
	 */
	public void setPie(PieDic pie) {
		this.pie = pie;
	}

	/**
	 * 
	 * @return
	 */
	public PosicionDic getPosicion() {
		return posicion;
	}

	/**
	 * 
	 * @param posicion
	 */
	public void setPosicion(PosicionDic posicion) {
		this.posicion = posicion;
	}

	/**
	 * 
	 * @return
	 */
	public Integer getDorsal() {
		return dorsal;
	}

	/**
	 * 
	 * @param dorsal
	 */
	public void setDorsal(Integer dorsal) {
		this.dorsal = dorsal;
	}

	/**
	 * 
	 * @param listaParticipaciones
	 */
	public void setListaParticipaciones(List<PartJugador> listaParticipaciones) {
		this.listaParticipaciones = listaParticipaciones;
	}

	/**
	 * 
	 * @return edad Edad del jugador
	 */
	public Integer getEdad() {
		if (edad == null) {
			calculaEdad();
		}
		return edad;
	}

	/**
	 * 
	 * @param edad
	 */
	public void setEdad(Integer edad) {
		this.edad = edad;
	}

	public byte[] getFotografia() {
		return fotografia;
	}

	public void setFotografia(byte[] fotografia) {
		this.fotografia = fotografia;
	}

}
